package fr.umlv.m2.jee.spij.framework.dao;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.List;

/**
 * @param <K> the primary key.
 * @param <T> the type object.
 */
public interface IDAO<K extends Serializable, T> {

    /**
     * Checks if the key already exists.
     *
     * @param key the primary key
     *
     * @return true if the key already exists, false otherwise.
     */
    boolean alreadyExists(K key);

    /**
     * Gets the object from it primary key.
     *
     * @param id the id.
     *
     * @return the object that got it id.
     */
    T getReference(K id);

    /**
     * Finds the object form it primary key.
     *
     * @param id the primary key.
     *
     * @return the object that got it id.
     */
    T findById(K id);

    /**
     * Finds the object from a query.
     *
     * @param query the query.
     *
     * @return a list of objects.
     */
    List<T> findByQuery(String query);

    /**
     * @param query the query.
     *
     * @return an object of type T.
     */
    T findEntityByQuery(String query);

    /**
     * @param query a query.
     *
     * @return a list of object.
     */
    List<T> findByNamedQuery(String query);

    /**
     * @param query a query.
     *
     * @return an object.
     */
    T findEntityByNamedQuery(String query);

    /**
     * @return a list of object.
     */
    List<T> findAll();

    /**
     * @return the number of object.
     */
    Long findCountAll();

    /**
     * @param toPersist the object to persist.
     *
     * @return the object persisted.
     */
    T persist(T toPersist);

    /**
     * @param toRemove the object to remove.
     */
    void remove(T toRemove);

    /**
     * Synchronize all the changes that are made to the persistent entities
     * back to the underlying database.
     */
    void flush();

    /**
     * Clears.
     */
    void clear();

    /**
     * @param isContained the object that is checked.
     *
     * @return true if the object is contained as an entity, false otherwise.
     */
    boolean contains(T isContained);

    /**
     * Updates the entity object with values taken from the database.
     * Any new values that are set to the entity objects
     * will be lost as a result of this method call.
     *
     * @param toRefresh The entity object updates with values taken from the DB
     */
    void refresh(T toRefresh);

    /**
     * @param toMerge the object to merge.
     *
     * @return an object of type T.
     */
    T merge(T toMerge);

    /**
     * @param query a query.
     *
     * @return a Query.
     */
    Query createQuery(String query);

    /**
     * @param query a query.
     *
     * @return a Query.
     */
    Query createNativeQuery(String query);

    /**
     * @param query a query.
     *
     * @return a Query.
     */
    Query createNamedQuery(String query);

    /**
     * @param newEntityManager the new entity manager.
     */
    void setEntityManager(EntityManager newEntityManager);

    /**
     * @return the entityManager.
     */
    EntityManager getEntityManager();

    /**
     * @return a list of Class.
     */
    Class<T> getEntityType();
}
